package com.jintian.smart.kernel.interceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.AbstractBeanFactory;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.lang.reflect.Field;

/**
 * springmvc处理拦截器
 * 1.切换线程的ClassLoader，用于beetl Function能够访问子Context中的Class
 * 2.用于MutiContextBeetlSpringViewResolver中获取子Context中的BeetlSpringViewResolver
 **/
public class MultiApplicationContextInterceptor implements HandlerInterceptor {
    private static final ThreadLocal<ClassLoader> local_OrgiClassLoader = new ThreadLocal<ClassLoader>();
    private static final ThreadLocal<BeanFactory> local_ModelApplicationContext = new ThreadLocal<BeanFactory>();

    public static BeanFactory getCurrentBeanFactory() {
        return local_ModelApplicationContext.get();
    }

    private void changeThreadClassLoad(ClassLoader classLoader) {
        if (Thread.currentThread().getContextClassLoader() != classLoader) {
            local_OrgiClassLoader.set(Thread.currentThread().getContextClassLoader());
            Thread.currentThread().setContextClassLoader(classLoader);
        }
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            Field f = ReflectionUtils.findField(handler.getClass(), "beanFactory");
            f.setAccessible(true);
            AbstractBeanFactory beanFactory = (AbstractBeanFactory) f.get(handler);
            if (beanFactory != null) {
                local_ModelApplicationContext.set(beanFactory);
                ClassLoader beanClassLoader = beanFactory.getBeanClassLoader();
                if (beanClassLoader != null) {
                    changeThreadClassLoad(beanClassLoader);
                }
            }
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 还原线程的ClassLoader
        if (local_OrgiClassLoader.get() != null && local_OrgiClassLoader.get() != Thread.currentThread().getContextClassLoader()) {
            Thread.currentThread().setContextClassLoader(local_OrgiClassLoader.get());
        }
        local_OrgiClassLoader.set(null);
        local_ModelApplicationContext.set(null);
    }
}
